package com.summer.data.connection.sessioninterface;

import com.summer.data.Jsql;
import com.summer.data.dialect.Dialect;
import com.summer.data.exception.SqlException;
import com.summer.data.logging.Logger;
import com.summer.data.logging.LoggerFactory;
import com.summer.data.table.BaseTable;
import com.summer.data.util.TableUtils;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 基于元数据的操作接口
 * @author 345480567@qq.com
 */
public interface MetaSessionInterface extends BaseSessionInterface, JsqlSessionInterface {

    class ColumnMeta {
        public String name;
        public String type;
        public String comment;
    }

    String getCurrentCatalog();

    String getCurrentSchema();

    default List<String> getCurrentTables() {
        String catalog = getCurrentCatalog();
        String schema = getCurrentSchema();
        return getTables(catalog, schema, "%");
    }

    default List<String> getCatalogs() {
        ArrayList<String> list = new ArrayList<>();
        try {
            Connection connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getCatalogs();
            while (resultSet.next()) {
                String string = resultSet.getString("TABLE_CAT");
                list.add(string);
            }
        } catch (SQLException e) {
            throw new SqlException(e);
        } finally {
            close();
        }
        return list;
    }

    default List<String> getSchemas(String catalogs) {
        ArrayList<String> list = new ArrayList<>();
        try {
            Connection connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getSchemas(catalogs, null);
            while (resultSet.next()) {
                String string = resultSet.getString("TABLE_SCHEM");
                list.add(string);
            }
        } catch (SQLException e) {
            throw new SqlException(e);
        } finally {
            close();
        }
        return list;
    }

    default List<String> getTables(String tableName) {
        String catalog = getCurrentCatalog();
        String schema = getCurrentSchema();
        return getTables(catalog, schema, tableName);
    }

    default List<String> getTables(String catalogs, String schema, String tableName) {
        ArrayList<String> list = new ArrayList<>();
        try {
            Connection connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getTables(
                    catalogs,
                    schema,
                    tableName,
                    new String[]{ "TABLE", "VIEW" }
            );
            while (resultSet.next()) {
                String string = resultSet.getString("TABLE_NAME");
                list.add(string);
            }
        } catch (SQLException e) {
            throw new SqlException(e);
        } finally {
            close();
        }
        return list;
    }

    default List<ColumnMeta> getColumns(String catalogs, String database, String table) {
        ArrayList<ColumnMeta> list = new ArrayList<>();
        try {
            Connection connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet resultSet = metaData.getColumns(
                    catalogs,
                    database,
                    table,
                    "%"
            );
            while (resultSet.next()) {
                ColumnMeta columnMeta = new ColumnMeta();
                columnMeta.name = resultSet.getString("COLUMN_NAME");
                columnMeta.type = resultSet.getString("TYPE_NAME");
                columnMeta.comment = resultSet.getString("REMARKS");
                list.add(columnMeta);
            }
        } catch (SQLException e) {
            throw new SqlException(e);
        } finally {
            close();
        }
        return list;
    }

    default <T extends BaseTable> void migrate(Class<T> clazz) {
        Dialect dialect = getDialect();

        List<String> tables = getTables(TableUtils.getTableName(clazz));

        // 创建表
        if (tables.isEmpty()) {
            List<Jsql> jsqlList = dialect.buildCreateTableSql(clazz);
            for (Jsql jsql : jsqlList) {
                executeUpdate(jsql);
            }
        } else {
        // 修改表结构
            Logger logger = LoggerFactory.getLogger(MetaSessionInterface.class);
            logger.info("表 %s 已经存在，请手动修改", TableUtils.getTableName(clazz));
//            List<Jsql> jsqlList = dialect.buildModifyTableSql(clazz);
//            for (Jsql jsql : jsqlList) {
//                executeUpdate(jsql);
//            }
        }

    }

    default <T extends BaseTable> void drop(Class<T> clazz) {
        Dialect dialect = getDialect();
        Jsql jsql = dialect.buildDropTableSql(clazz);
        executeUpdate(jsql);
    }

}
